package com.open.rbac.config.executor;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

/**
 * 线程池配置
 *
 * @author Riche's
 * @since 2025/4/29
 */
@Slf4j
@Configuration
public class ExecutorConfig {

    @Bean("workPoolProperties")
    @ConfigurationProperties(prefix = "admin.work-pool")
    public ThreadPoolProperties getWorkPoolProperties() {
        return new ThreadPoolProperties();
    }

    @Bean("logPoolProperties")
    @ConfigurationProperties(prefix = "admin.log-pool")
    public ThreadPoolProperties getLogPoolProperties() {
        return new ThreadPoolProperties();
    }


    @Bean("openTaskExecutors")
    public List<Executor> openTaskExecutors() {
        return Collections.synchronizedList(new LinkedList<>());
    }

    /**
     * 多个不同的任务建议配置多个线程池 避免影响其他业务
     * SpringCloud 使用 Hystrix 实现业务线程池隔离
     * 线程数量大小
     *   IO密集型： CPU核数 * 2
     *   计算密集型： CPU核数 + 1
     */
    @Bean("workPoolExecutor")
    public OpenTaskExecutor workPoolExecutor() {
        ThreadPoolProperties poolProperties = getWorkPoolProperties();
        OpenTaskExecutor workPoolExecutor = newOpenTaskExecutor(poolProperties);
        openTaskExecutors().add(workPoolExecutor);
        log.info("初始化工作线程池: {}", poolProperties);
        return workPoolExecutor;
    }

    @Bean("logPoolExecutor")
    public OpenTaskExecutor logPoolExecutor() {
        ThreadPoolProperties poolProperties = getLogPoolProperties();
        OpenTaskExecutor logPoolExecutor = newOpenTaskExecutor(poolProperties);
        openTaskExecutors().add(logPoolExecutor);
        log.info("初始化日志线程池: {}", poolProperties);
        return logPoolExecutor;
    }

    private OpenTaskExecutor newOpenTaskExecutor(ThreadPoolProperties poolProperties) {
        OpenTaskExecutor openTaskExecutor = new OpenTaskExecutor(poolProperties.getPoolName());
        // 设置核心线程数
        openTaskExecutor.setCorePoolSize(poolProperties.getCorePoolSize());
        // 设置空闲线程超时时间
        openTaskExecutor.setKeepAliveSeconds(poolProperties.getKeepAliveSeconds());
        // 设置最大线程数
        openTaskExecutor.setMaxPoolSize(poolProperties.getMaxPoolSize());
        // 设置缓冲对象大小
        openTaskExecutor.setQueueCapacity(poolProperties.getQueueCapacity());
        openTaskExecutor.setThreadNamePrefix(poolProperties.getThreadNamePrefix());
        // 拒绝策略
        openTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                openTaskExecutor.getRejectedCount().incrementAndGet();
                log.warn("[{}]线程池任务被拒绝", poolProperties.getPoolName());
                super.rejectedExecution(r, e);
            }
        });

        // 销毁之前执行Shutdown
        openTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        openTaskExecutor.initialize();
        return openTaskExecutor;
    }


    /**
     * 定时任务线程池
     */
    @Bean("openTaskExecutor")
    public ThreadPoolTaskScheduler openTaskExecutor() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(5);
        scheduler.setThreadNamePrefix("SCHEDULER-");
        scheduler.setRemoveOnCancelPolicy(true);
        scheduler.setErrorHandler(throwable ->
                // 处理调度任务中的异常
                log.error("{}", throwable.getMessage(), throwable)
        );
        return scheduler;
    }

}
